module molecules
   use precision
   implicit none
   private

   type molecule
      private
	  real(adequate) mass
	  integer charge
	  integer number_of_elements, number_of_atoms
   end type molecule

   public molecule, mass, charge, set_mass, set_charge, new, as_string

   interface new
      module procedure molecule_new
   end interface new

   interface mass
      module procedure molecule_mass
   end interface mass

   interface charge
      module procedure molecule_charge
   end interface charge

   interface set_mass
      module procedure set_molecule_mass
   end interface set_mass

   interface set_charge
      module procedure set_molecule_charge
   end interface set_charge

   interface as_string
      module procedure molecule_as_string
   end interface as_string

   contains

   subroutine molecule_new (a, name)
      character*(*), intent(in):: name
	  type(molecule), intent(out):: a
	  select case(name)
	  case("O2")
	     a = molecule(32.0, 0, 1, 2)
	  case("H2O")
	     a = molecule(18.0, 0, 2, 3)
	  case("CH4")
	     a = molecule(16.0, 0, 2, 5)
	  case default
	     ! hm...
		 stop "Illegal molecule creation attempted."
	  end select 
   end subroutine molecule_new

   function molecule_mass (a) 
      real(adequate) molecule_mass
	  type(molecule), intent(in):: a
	  molecule_mass = a%mass
   end function molecule_mass

   function molecule_charge (a) 
      real(adequate) molecule_charge
	  type(molecule), intent(in):: a
	  molecule_charge = a%charge
   end function molecule_charge

   function molecule_as_string (a)
      type(molecule), intent(in):: a
	  character*64 molecule_as_string
	  write (molecule_as_string, 100) a%mass, a%charge, a%number_of_elements, &
	     a%number_of_atoms
100 format("molecule( ", e14.4, ", ", i2, ", ", i2, ", ", i5")")
   end function molecule_as_string

   subroutine set_molecule_mass (a, m)
      type(molecule), intent(inout):: a
	  real(adequate), intent(in):: m
	  a%mass = m
   end subroutine set_molecule_mass

   subroutine set_molecule_charge (a, c)
      type(molecule), intent(inout):: a
	  integer, intent(in):: c
	  a%charge = c
   end subroutine set_molecule_charge

end module molecules


